﻿namespace FATEFAKE
{
    #region using directives
    using System;
    using System.IO;
    using System.Text;
    #endregion

    class Options
    {
        private string fateFile;

        private string ffmpegExecutable;

        private string toolsPath;

        private string dataPath;

        private bool silent;

        private string referencePath;

        private string fateSuitePath;

        private string tempPath;

        private string testsPath;

        private string ffmpegPrependCmdLine;

        private bool printFfmpegCommandLine;

        private bool useWinFile;

        public Options(string[] args)
        {
            this.SetDefaults();
            this.ParseCommandLineArgs(args);
        }

        public bool CheckOptions()
        {
            if (!Directory.Exists(this.TempPath))
            {
                // try to create the folder
                Directory.CreateDirectory(this.TempPath);
            }

            return true;
        }

        public void PrintOptions()
        {
            Console.WriteLine("Options:");
            Console.WriteLine("--------");
            Console.WriteLine("FFmpeg-Executable: \"{0}\"", this.FfmpegExecutable);
            Console.WriteLine("FATE-Commands: \"{0}\"", this.FateFile);
            Console.WriteLine(string.Empty);
        }

        /// <summary>
        /// Gets the the full path for the FFmpeg executable.
        /// </summary>
        /// <value>
        /// The full path for the FFmpeg executable.
        /// </value>
        public string FfmpegExecutable
        {
            get { return this.ffmpegExecutable; }
        }

        public string DataPath
        {
            get { return this.dataPath; }
        }

        public string FateFile
        {
            get { return this.fateFile; }
        }

        public bool Silent
        {
            get { return this.silent; }
        }

        public bool UseWinfile
        {
            get { return this.useWinFile; }
        }

        public string ReferencePath
        {
            get { return this.referencePath; }
        }

        public string FateSuitePath
        {
            get { return this.fateSuitePath; }
        }

        public string ToolsPath
        {
            get { return this.toolsPath; }
        }

        public string TempPath
        {
            get { return this.tempPath; }
        }

        public string TestsPath
        {
            get { return this.testsPath; }
        }

        public string PrependFfmpegCmdLine
        {
            get { return this.ffmpegPrependCmdLine; }
        }

        public bool PrintFfmpegCommandLine
        {
            get { return this.printFfmpegCommandLine; }
        }

        private void SetDefaults()
        {
            this.ffmpegExecutable = FindFfmpegDefault();
            this.SetFateDataPaths(FindDefaultDataPath());
            this.fateFile = FindDefaultFateCommandsFile();
            this.toolsPath = FindToolsPathDefault();
            this.useWinFile = false;
        }

        private void SetFateDataPaths(string path)
        {
            //this.dataPath = Path.Combine(path, "data");
            //this.testsPath = Path.Combine(path, "tests");
            //this.referencePath = Path.Combine(path, @"ref\fate");
            //this.fateSuitePath = Path.Combine(path, "fate-suite");
            this.dataPath = Path.Combine(path, @"tests\data");
            this.testsPath = Path.Combine(path, "tests");
            this.referencePath = Path.Combine(path, @"tests\ref\fate");
            this.fateSuitePath = Path.Combine(path, "fate-suite");
            this.tempPath = Path.Combine(path, "temp");
        }

        private static string FindDefaultDataPath()
        {
            const string DefaultPath = @"..\..\FATEDATA\";
            return Path.GetFullPath(DefaultPath);
        }

        private static string FindDefaultFateCommandsFile()
        {
            return Path.GetFullPath(@"..\..\fatecommands\CompleteFateCommands.txt");
        }

        private static string FindFfmpegDefault()
        {
#if DEBUG
            const string SolutionDir = "Debug";
#else
            const string SolutionDir = "Release";
#endif
            string path = @"..\..\..\Build\" + SolutionDir + @"\winffmpeg.exe";
            if (File.Exists(path))
            {
                return Path.GetFullPath(path);
            }

            return Path.GetFullPath(@".\winffmpeg.exe");
        }

        private static string FindToolsPathDefault()
        {
            const string DefaultPath = @"..\..\..\Build\{0}\tiny_psnr.exe";
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(DefaultPath, "Release");
            if (File.Exists(sb.ToString()))
            {
                return Path.GetDirectoryName(Path.GetFullPath(sb.ToString()));
            }

            sb.Clear();
            sb.AppendFormat(DefaultPath, "Debug");
            if (File.Exists(sb.ToString()))
            {
                return Path.GetDirectoryName(Path.GetFullPath(sb.ToString()));
            }

            return string.Empty;
        }

        private static string GetNextArgument(int index, string[] args)
        {
            return args[index + 1];
        }

        private static bool IsSwitch(string s, string shortSwitchName, string longSwitchName)
        {
            if (!(s.StartsWith("-") || s.StartsWith("/")))
            {
                return false;
            }

            string s2 = s.Substring(1);
            if (string.CompareOrdinal(s2, shortSwitchName) == 0 || string.CompareOrdinal(s2, longSwitchName) == 0)
            {
                return true;
            }

            return false;
        }

        private void ParseCommandLineArgs(string[] args)
        {
            for (int index = 0; index < args.Length; index++)
            {
                string s = args[index];
                if (IsSwitch(s, "s", "silent"))
                {
                    this.silent = true;
                }
                else if (IsSwitch(s, "e", "exe"))
                {
                    this.ffmpegExecutable = GetNextArgument(index++, args);
                }
                else if (IsSwitch(s, "f", "fatefile"))
                {
                    this.fateFile = GetNextArgument(index++, args);
                }
                else if (IsSwitch(s, "d", "fatedata"))
                {
                    string fateData = GetNextArgument(index++, args);
                    this.SetFateDataPaths(fateData);
                }
                else if (IsSwitch(s, "p", "prepend"))
                {
                    this.ffmpegPrependCmdLine = GetNextArgument(index++, args);
                }
                else if (IsSwitch(s, "c", "print-commandline"))
                {
                    this.printFfmpegCommandLine = true;
                }
                else if (IsSwitch(s,"w","use-winfile"))
                {
                    this.useWinFile = true;
                }
            }
        }
    }
}
